package com.facepp.demo;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.facepp.error.FaceppParseException;
import com.facepp.http.HttpRequests;
import com.facepp.http.PostParameters;

import android.app.Activity;
import android.content.ClipData;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.SystemClock;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class EnterActivity extends Activity {

    private static final int REQUEST_CODE_CAPTURE_REGIST_PHOTO = 0;
    private static final int REQUEST_CODE_CAPTURE_VERIFY_PHOTO = 1;
    private static final String SAVED_IMAGE_DIR_PATH = Environment.getExternalStorageDirectory().getAbsolutePath();
    public static final String TAG = "TARO";
//    private static final String SAVED_IMAGE_DIR_PATH = "/data/";
    private String mCapturePath = null;
    private OnClickListener mTakeRegistPhoto = new OnClickListener() {
        public void onClick(View v) {
            getImageFromCamera(REQUEST_CODE_CAPTURE_REGIST_PHOTO);
        }
    };
    private OnClickListener mTakeVerifyPhoto = new OnClickListener() {
        public void onClick(View v) {
            getImageFromCamera(REQUEST_CODE_CAPTURE_VERIFY_PHOTO);
        }
    };
    private ImageView mRegistPhoto;
    private ImageView mVerifyPhoto;
    private String mRegistPhotoPath;
    private String mVerifyPhotoPath;
    private TextView mRegistResult;
    private TextView mVerifyResult;
    private boolean mWorking = false;
    private OnClickListener mRegistPhotoListener = new OnClickListener() {
        public void onClick(View v) {
            synchronized (EnterActivity.this) {
                if (mRegistPhotoPath == null) {
                    Toast.makeText(EnterActivity.this, "请先设置注册头像!", Toast.LENGTH_LONG).show();
                    return;
                }
                if (mHttpRequests == null) {
                    Toast.makeText(EnterActivity.this, "初始化未完成，请稍候...", Toast.LENGTH_LONG).show();
                    return;
                }
                if (mWorking) {
                    Toast.makeText(EnterActivity.this, "正在处理...", Toast.LENGTH_LONG).show();
                    return;
                }
                mWorking = true;
            }
            new RegistTask().execute(mRegistPhotoPath);
        }
    };

    private String mPersonName = "zhangshuo";
    public String mPersonTag = "feishuo";
    public String mFacesetName = "shuoface";
    public String mFacesetTag = "feishuofaceset";
    public String mGroupName = "shuofacegroup";
    private class RegistTask extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... params) {
            regist(params[0]);
            return null;
        }

        private void regist(String photoUrl) {
            JSONObject result = null;
            long token = System.currentTimeMillis();
            mPersonName += token;
            mPersonTag += token;
            mFacesetName += token;
            mFacesetTag += token;
            mGroupName += token;
            try {

                mDLog(Charset.forName("UTF-8").name());

                mDLog("Start Regist Task: " + photoUrl);

                // detection/detect
                result = mHttpRequests.detectionDetect(new PostParameters()
                        .setImg(new File(photoUrl)));
//                result = mHttpRequests.detectionDetect(new PostParameters()
//                .setUrl("http://cn.faceplusplus.com/wp-content/themes/faceplusplus/assets/img/demo/9.jpg"));
                mDLog("detection/detect: " + result);

                JSONArray faceArray = result.getJSONArray("face");
//                mDLog("detection/detect: " + result.getJSONArray("face")
//                        .getJSONObject(0).getJSONObject("position")
//                        .getJSONObject("center"));

                // -----------------Person-----------------
                // person/create
                mDLog("person/create");
//                for (int i = 0; i < result.getJSONArray("face").length(); ++i)
//                    mDLog(mHttpRequests
//                            .personCreate(new PostParameters()
//                                    .setPersonName("person_" + i)));
                if (faceArray.length() < 1) {
                    mDLog("person/create fail, no face detected");
                    return;
                }
                mDLog(mHttpRequests.personCreate(new PostParameters().setPersonName(mPersonName)));

//                new PostParameters()
//                        .setPersonName("person_" + 0)
//                        .setFaceId(
//                                result.getJSONArray("face")
//                                        .getJSONObject(0)
//                                        .getString("face_id"))
//                        .getMultiPart().writeTo(System.out);

                // person/add_face
                mDLog("\nperson/add_face");
//                for (int i = 0; i < result.getJSONArray("face").length(); ++i)
//                    mDLog(mHttpRequests
//                            .personAddFace(new PostParameters()
//                                    .setPersonName("person_" + i)
//                                    .setFaceId(
//                                            result.getJSONArray("face")
//                                                    .getJSONObject(i)
//                                                    .getString("face_id"))));
                mDLog(mHttpRequests.personAddFace(new PostParameters().setPersonName(mPersonName)
                        .setFaceId(faceArray.getJSONObject(0).getString("face_id"))));

                // person/set_info
                mDLog("\nperson/set_info");
//                for (int i = 0; i < result.getJSONArray("face").length(); ++i) {
//                    new PostParameters().setPersonName("person_" + i)
//                            .setTag("tag_" + i).getMultiPart()
//                            .writeTo(System.out);
//                    mDLog(mHttpRequests
//                            .personSetInfo(new PostParameters()
//                                    .setPersonName("person_" + i).setTag(
//                                            "tag_" + i)));
//                }
                mDLog(mHttpRequests.personSetInfo(new PostParameters().setPersonName(mPersonName).setTag(mPersonTag)));

                // person/get_info
                mDLog("\nperson/get_info");
//                for (int i = 0; i < result.getJSONArray("face").length(); ++i)
//                    mDLog(mHttpRequests
//                            .personGetInfo(new PostParameters()
//                                    .setPersonName("person_" + i)));
                mDLog(mHttpRequests.personGetInfo(new PostParameters().setPersonName(mPersonName)));

                // -----------------Faceset-----------------
                // faceset/create
                mDLog("\nfaceset/create");
//                for (int i = 0; i < result.getJSONArray("face").length(); ++i)
//                    mDLog(mHttpRequests
//                            .facesetCreate(new PostParameters()
//                                    .setFacesetName("faceset_" + token)));
                mDLog(mHttpRequests.facesetCreate(new PostParameters().setFacesetName(mFacesetName )));

                // faceset/add_face
                mDLog("\nfaceset/add_face");
//                for (int i = 0; i < result.getJSONArray("face").length(); ++i)
//                    mDLog(mHttpRequests
//                            .facesetAddFace(new PostParameters()
//                                    .setFacesetName("faceset_" + i)
//                                    .setFaceId(
//                                            result.getJSONArray("face")
//                                                    .getJSONObject(i)
//                                                    .getString("face_id"))));
                mDLog(mHttpRequests
                        .facesetAddFace(new PostParameters().setFacesetName(mFacesetName)
                                .setFaceId(faceArray.getJSONObject(0).getString("face_id"))));

                // faceset/set_info
                mDLog("\nfaceset/set_info");
//                for (int i = 0; i < result.getJSONArray("face").length(); ++i) {
//                    new PostParameters().setFacesetName("faceset_" + i)
//                            .setTag("���� tag_" + i).getMultiPart()
//                            .writeTo(System.out);
//                    mDLog(mHttpRequests
//                            .facesetSetInfo(new PostParameters()
//                                    .setFacesetName("faceset_" + i).setTag(
//                                            "���� tag_" + i)));
//                }
                mDLog(mHttpRequests
                        .facesetSetInfo(new PostParameters()
                                .setFacesetName(mFacesetName).setTag(mFacesetTag )));

                // faceset/get_info
                mDLog("\nfaceset/get_info");
//                for (int i = 0; i < result.getJSONArray("face").length(); ++i)
//                    mDLog(mHttpRequests
//                            .facesetGetInfo(new PostParameters()
//                                    .setFacesetName("faceset_" + i)));
                mDLog(mHttpRequests
                        .facesetGetInfo(new PostParameters()
                                .setFacesetName(mFacesetName)));

                // -----------------Group-----------------
                // group/create
                mDLog("\ngroup/create");
                mDLog(mHttpRequests
                        .groupCreate(new PostParameters()
                                .setGroupName(mGroupName )));

                // group/add_person
                mDLog("\ngroup/add_person");
//                ArrayList<String> personList = new ArrayList<String>();
//                for (int i = 0; i < result.getJSONArray("face").length(); ++i)
//                    personList.add("person_" + i);

//                new PostParameters().setGroupName("group_0")
//                        .setPersonName(personList).getMultiPart()
//                        .writeTo(System.out);
                mDLog(mHttpRequests
                        .groupAddPerson(new PostParameters().setGroupName(
                                mGroupName).setPersonName(mPersonName)));

                // group/set_info
                mDLog("\ngroup/set_info");
                mDLog(mHttpRequests
                        .groupSetInfo(new PostParameters().setGroupName(
                                mGroupName).setTag("group tag")));

                // group/get_info
                mDLog("\ngroup/get_info");
                mDLog(mHttpRequests
                        .groupGetInfo(new PostParameters()
                                .setGroupName(mGroupName)));

                // -----------------Recognition-----------------

                // recognition/train
                JSONObject syncRet = null;

                System.out.println("\ntrain/Identify");
                syncRet = mHttpRequests.trainIdentify(new PostParameters()
                        .setGroupName(mGroupName));
                System.out.println(syncRet);
                System.out.println(mHttpRequests.getSessionSync(syncRet
                        .getString("session_id")));

                System.out.println("\ntrain/verify");
                syncRet = mHttpRequests.trainVerify(new PostParameters()
                .setPersonName(mPersonName));
                System.out.println(mHttpRequests.getSessionSync(syncRet
                            .get("session_id").toString()));
            } catch (FaceppParseException fpe) {
                mELog("FaceappParseException: ", fpe);
            } catch (JSONException e) {
                mELog("JSONException: ", e);
                // TODO Auto-generated catch block
            } finally {
//                if (result == null) {
//                    return;
//                }
//                try {
//                    for (int i = 1; i < result.getJSONArray("face")
//                            .length(); ++i) {
//                        mHttpRequests.personDelete(new PostParameters()
//                                .setPersonName("person_" + i));
//                        mHttpRequests.facesetDelete(new PostParameters()
//                                .setFacesetName("faceset_" + i));
//                    }
//                } catch (JSONException e) {
//                    mELog("JSONException: ", e);
//                } catch (FaceppParseException e) {
//                    mELog("FaceappParseException: ", e);
//                }
            }
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            mRegistResult.setText(result);
            synchronized (EnterActivity.this) {
                mWorking = false;
            }
        }
    }

    private OnClickListener mVerifyPhotoListener = new OnClickListener() {
        public void onClick(View v) {
            synchronized (EnterActivity.this) {
                if (mVerifyPhotoPath == null) {
                    Toast.makeText(EnterActivity.this, "请先设置需要验证的头像!", Toast.LENGTH_LONG).show();
                    return;
                }
                if (mHttpRequests == null) {
                    Toast.makeText(EnterActivity.this, "初始化未完成，请稍候...", Toast.LENGTH_LONG).show();
                    return;
                }
                if (mWorking) {
                    Toast.makeText(EnterActivity.this, "正在处理...", Toast.LENGTH_LONG).show();
                    return;
                }
                mWorking = true;
            }
            new VerifyTask().execute(mRegistPhotoPath, mVerifyPhotoPath);
        }
    };
    private class VerifyTask extends AsyncTask<String, Void, String> {
        @Override
        protected String doInBackground(String... params) {
            
            return verify(params[0], params[1]);
        }

        private String verify(String registPath, String verifyPath) {
            String res = "";

            JSONObject result = null;

            try {

                mDLog(Charset.forName("UTF-8").name());

                mDLog("start verify task: " + verifyPath);

                // recognition/recognize
                mDLog("\nrecognition/identify");
                result = mHttpRequests
                        .recognitionIdentify(new PostParameters()
                                .setGroupName(mGroupName)
                                .setImg(new File(verifyPath)));
//                result = mHttpRequests
//                        .recognitionIdentify(new PostParameters()
//                        .setGroupName(mGroupName)
//                        .setUrl("http://cn.faceplusplus.com/wp-content/themes/faceplusplus/assets/img/demo/9.jpg"));

                mDLog(result);
                res = result.getJSONArray("face").getJSONObject(0).getJSONArray("candidate").getJSONObject(0).getString("confidence");
//                // recognition/verify
//                mDLog("\nrecognition/verify");
//                mDLog(mHttpRequests
//                        .recognitionVerify(new PostParameters()
//                                .setPersonName("person_0").setFaceId(
//                                        result.getJSONArray("face")
//                                                .getJSONObject(0)
//                                                .getString("face_id"))));
//                mDLog(mHttpRequests
//                        .recognitionVerify(new PostParameters()
//                                .setPersonName("person_1").setFaceId(
//                                        result.getJSONArray("face")
//                                                .getJSONObject(0)
//                                                .getString("face_id"))));

                // -----------------Info-----------------
                // info/get_app
                mDLog("\ninfo/get_app");
                mDLog(mHttpRequests.infoGetApp());

//                // info/get_face
//                mDLog("\ninfo/get_app");
//                mDLog(mHttpRequests
//                        .infoGetFace(new PostParameters().setFaceId(result
//                                .getJSONArray("face").getJSONObject(0)
//                                .getString("face_id"))));

                // info/get_group_list
                mDLog("\ninfo/get_group_list");
                mDLog(mHttpRequests.infoGetGroupList());

//                // info/get_image
//                mDLog("\ninfo/get_image");
//                mDLog(mHttpRequests
//                        .infoGetImage(new PostParameters().setImgId(result
//                                .getString("img_id"))));

                // info/get_person_list
                mDLog("\ninfo/get_person_list");
                mDLog(mHttpRequests.infoGetPersonList());

                // info/get_quota
                mDLog("\ninfo/get_quota");
                mDLog(mHttpRequests.infoGetQuota());

//                // info/get_session
//                mDLog("\ninfo/get_session");
//                mDLog(mHttpRequests
//                        .infoGetSession(new PostParameters()
//                                .setSessionId(result
//                                        .getString("session_id"))));

//                // -----At last----
//                // person/remove_face
//                mDLog("\nperson/remove_face");
//                mDLog(mHttpRequests
//                        .personRemoveFace(new PostParameters()
//                                .setPersonName("person_0").setFaceId(
//                                        result.getJSONArray("face")
//                                                .getJSONObject(0)
//                                                .getString("face_id"))));
//
//                // group/delete
//                mDLog("\ngroup/delete");
//                mDLog(mHttpRequests
//                        .groupDelete(new PostParameters()
//                                .setGroupName("group_0")));
//
//                // person/delete
//                mDLog("\nperson/delete");
//                mDLog(mHttpRequests
//                        .personDelete(new PostParameters()
//                                .setPersonName("person_0")));
//
//                // faceset/delete
//                mDLog("\nfaceset/delete");
//                mDLog(mHttpRequests
//                        .facesetDelete(new PostParameters()
//                                .setFacesetName("faceset_0")));

            } catch (FaceppParseException fpe) {
                mELog("FaceappParseException: ", fpe);
            } catch (JSONException e) {
                mELog("JSONException: ", e);
                e.printStackTrace();
            } finally {
//                if (result == null) {
//                    return;
//                }
//                try {
//                    for (int i = 0; i < result.getJSONArray("face")
//                            .length(); ++i) {
//                        mHttpRequests.personDelete(new PostParameters()
//                                .setPersonName("person_" + i));
//                        mHttpRequests.facesetDelete(new PostParameters()
//                                .setFacesetName("faceset_" + i));
//                    }
//                } catch (JSONException e) {
//                    mELog("JSONException: ", e);
//                } catch (FaceppParseException e) {
//                    mELog("FaceappParseException: ", e);
//                }
            }
            return res;
        }
        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);

            mVerifyResult.setText("匹配度： " + result);
            synchronized (EnterActivity.this) {
                mWorking = false;
            }
        }
    };
    protected HttpRequests mHttpRequests;
    private String mImageDirPath;

    protected void getImageFromCamera(int requestCode) {
        String state = Environment.getExternalStorageState();
        if (state.equals(Environment.MEDIA_MOUNTED)) {
            Intent getImageByCamera = new Intent(
                    MediaStore.ACTION_IMAGE_CAPTURE);
            String out_file_path = SAVED_IMAGE_DIR_PATH;
            File dir = new File(out_file_path + "/aaaa/");
            if (!dir.exists()) {
                dir.mkdirs();
            }
            mCapturePath = out_file_path + "/aaaa/" + System.currentTimeMillis()
                    + ".jpg";
            File file = new File(mCapturePath);
            getImageByCamera.putExtra(MediaStore.EXTRA_OUTPUT,
                    Uri.fromFile(file));
            getImageByCamera.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            getImageByCamera.setClipData(ClipData.newRawUri(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file)));
            getImageByCamera.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
            startActivityForResult(getImageByCamera, requestCode);
        } else {
            Toast.makeText(getApplicationContext(), "请确认已经插入SD卡",
                    Toast.LENGTH_LONG).show();
        }
    }

    public void mELog(String msg, Exception e) {
        Log.e(TAG, msg, e);
    }
    
    public void mDLog(Object jsonObject) {
        Log.d(TAG, jsonObject.toString());
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.entry_main);
        File imageDir = getCacheDir();
        imageDir.mkdirs();
        mImageDirPath = imageDir.getAbsolutePath();
        initView();
        new Thread(mInitRequest).start();
    }

    private void initView() {
        Button takeRegist = (Button) findViewById(R.id.take_regist_photo_id);
        takeRegist.setOnClickListener(mTakeRegistPhoto);
        Button takeVerify = (Button) findViewById(R.id.take_verify_photo_id);
        takeVerify.setOnClickListener(mTakeVerifyPhoto);

        mRegistPhoto = (ImageView)findViewById(R.id.regist_photo);
        mVerifyPhoto = (ImageView)findViewById(R.id.verify_photo);

        Button regist = (Button)findViewById(R.id.regist_id);
        regist.setOnClickListener(mRegistPhotoListener );
        Button verify = (Button)findViewById(R.id.verify_id);
        verify.setOnClickListener(mVerifyPhotoListener);
//        regist.setVisibility(View.GONE);

        mRegistResult = (TextView)findViewById(R.id.regist_result);
        mVerifyResult = (TextView)findViewById(R.id.verify_result);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK && requestCode == REQUEST_CODE_CAPTURE_REGIST_PHOTO ) {
            mRegistPhoto.setImageBitmap(null);
            mRegistPhotoPath = mCapturePath;
            mRegistPhoto.setImageBitmap(getimage(mCapturePath));
        } else if (resultCode == RESULT_OK && requestCode == REQUEST_CODE_CAPTURE_VERIFY_PHOTO ) {
            mVerifyPhoto.setImageBitmap(null);
            mVerifyPhotoPath = mCapturePath;
            mVerifyPhoto.setImageBitmap(getimage(mCapturePath));
        }
    }

    private Bitmap getimage(String srcPath) {
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        //开始读入图片，此时把options.inJustDecodeBounds 设回true了
        newOpts.inJustDecodeBounds = true;
        Bitmap bitmap = BitmapFactory.decodeFile(srcPath,newOpts);//此时返回bm为空
        
        newOpts.inJustDecodeBounds = false;
        int w = newOpts.outWidth;
        int h = newOpts.outHeight;
        //现在主流手机比较多是800*480分辨率，所以高和宽我们设置为
        float hh = 400f;//这里设置高度为800f
        float ww = 240f;//这里设置宽度为480f
        //缩放比。由于是固定比例缩放，只用高或者宽其中一个数据进行计算即可
        int be = 1;//be=1表示不缩放
        if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
            be = (int) (newOpts.outWidth / ww);
        } else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放
            be = (int) (newOpts.outHeight / hh);
        }
        if (be <= 0)
            be = 1;
        newOpts.inSampleSize = be;//设置缩放比例
        //重新读入图片，注意此时已经把options.inJustDecodeBounds 设回false了
        bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
        return compressImage(bitmap);//压缩好比例大小后再进行质量压缩
    }

    private Bitmap compressImage(Bitmap image) {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
        int options = 100;
        while ( baos.toByteArray().length / 1024>100) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩       
            baos.reset();//重置baos即清空baos
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%，把压缩后的数据存放到baos中
            options -= 10;//每次都减少10
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片
        return bitmap;
    }

    private Runnable mInitRequest = new Runnable() {
        public void run() {
            // replace api_key and api_secret here (note)
            mHttpRequests = new HttpRequests(
                    "9d4a704debbdbaf708d90dfecf9c01e0",
                    "tmnebfwTPBmfrzhcCpzw7KpsaRzOzuuI", true, true);
        }
    };
}
